package org.fioma.tree;

import org.fioma.general.Tools;

public abstract class LabelRef<L extends LabelRef<L, W>, W> implements Label<L> {

	protected W word;
	protected int start, length;
	protected LabelRefFactory<L, W> labelFactory;

	public LabelRef(W word, int start, int length, LabelRefFactory<L, W> labelFactory) {
		this.word = word;
		this.start = start;
		this.length = length;
		// setStartLength(start, length);
		this.labelFactory = labelFactory;
	}

	// public LabelRefBytes(byte[] word) {
	// this.word = word;
	// this.pos = 0;
	// this.length = word[0];
	// }

	public W getWord() {
		return word;
	}

	public abstract int getWordLength();

	public int getStart() {
		return start;
	}

	@Override
	public char getChar(int pos) {
		return Tools.transformToChar(getByte(pos));
	}

	// public void setStartLength(int start, int length) {
	// if (start < 0 || start + length > getLength()) {
	// throw new RuntimeException("Start " + start + " and length "
	// + length + " invalid in the word with length "
	// + getLength());
	// }
	// this.start = start;
	// this.length = length;
	// }
	//
	@Override
	public int getLength() {
		return length;
	}

	@Override
	public L substring(int start, int length) {
		if (start < 0 || start + length > getLength()) {
			throw new RuntimeException("Start " + start + " and length " + length + " invalid in the word with length " + getLength());
		}
		L ret = createLabel(getWord(), getStart() + start, length);
		return ret;
	}

	protected L createLabel(W word, int start, int length) {
		return labelFactory.createLabel(word, start, length);
	}

	@Override
	public L substring(int start) {
		return substring(start, getLength() - start);
	}

	@Override
	public int getMismatch(Label word) {
		int i;
		for (i = 0; i < getLength() && i < word.getLength(); i++) {
			if (getChar(i) != word.getChar(i)) {
				return i;
			}
		}
		if (getLength() == word.getLength()) {
			return -1;
		}
		return i;
	}

	@Override
	public String toString() {
		StringBuffer ret = new StringBuffer();
		for (int i = 0; i < getLength(); i++) {
			ret.append(getChar(i));
		}
		return ret.toString();
	}

	public LabelRefFactory<L, W> getLabelFactory() {
		return labelFactory;
	}

	public void setLabelFactory(LabelRefFactory<L, W> labelFactory) {
		this.labelFactory = labelFactory;
	}

	public void setWord(W word) {
		this.word = word;
	}

	public void setStart(int start) {
		this.start = start;
	}

	public void setLength(int length) {
		this.length = length;
	}

}
